package com.hcj.springcloud.chat;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 单人聊天或者多人聊天，依据groupId来发消息，
 * <p>注意：</p>
 * 在同一个分组内的用户，可以收到消息
 * WebSocket 聊天服务端
 *
 * @see ServerEndpoint WebSocket服务端 需指定端点的访问路径
 * @see Session   WebSocket会话对象 通过它给客户端发送消息
 */
@Slf4j
@Component
@ServerEndpoint("/chat/{userName}/{groupId}")
public class One2ManyChatServer {

    /**
     * 全部在线会话  PS: 基于场景考虑 这里使用线程安全的Map存储会话对象。
     */
    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();


    /**
     * 当客户端打开连接：1.添加会话对象 2.更新在线人数
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userName") String userName, @PathParam("groupId") String groupId) throws IOException {
        log.info("客户【{}】连接进来....sessionId={}", userName, session.getId());
        onlineSessions.put(session.getId(), session);
        session.getUserProperties().put("user", userName);
        session.getUserProperties().put("groupId", groupId);



        sendMessageToAll(Message.jsonStr(Message.ENTER, "", "", onlineSessions.size()), session);
    }

    /**
     * 当客户端发送消息：1.获取它的用户名和消息 2.发送消息给所有人
     * <p>
     * PS: 这里约定传递的消息为JSON字符串 方便传递更多参数！
     */
    @OnMessage
    public void onMessage(Session session, String jsonStr) throws IOException {
        log.info("消息来临：{}", jsonStr);
        Message message = JSON.parseObject(jsonStr, Message.class);
        sendMessageToAll(Message.jsonStr(Message.SPEAK, message.getUsername(), message.getMsg(), onlineSessions.size()), session);
    }

    /**
     * 当关闭连接：1.移除会话对象 2.更新在线人数
     */
    @OnClose
    public void onClose(Session session) throws IOException {
        log.info("客户【{}】断开连接....sessionId={}", session.getUserProperties().get("user"), session.getId());
        onlineSessions.remove(session.getId());
        sendMessageToAll(Message.jsonStr(Message.QUIT, "", "", onlineSessions.size()), session);
    }

    /**
     * 当通信发生异常：打印错误日志
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 公共方法：发送信息给所有人
     */
    private static void sendMessageToAll(String msg, Session session) throws IOException {
        log.info("sendMessageToAll中 sessionId={}", session.getId());
        Session session1 = onlineSessions.get(session.getId());
        log.info("onlineSessions中 sessionId={}", session1.getId());
        //获取所有人的会话对象
        Set<Session> users = session.getOpenSessions();
        //获取发送人
        String sendUserGroupId = session.getUserProperties().get("groupId").toString();
        //发送给所有在一个组内的用户
        for (Session user : users) {
            if(user.getUserProperties().get("groupId").equals(sendUserGroupId)){
                user.getBasicRemote().sendText(msg);
            }
        }
    }

}
